package com.csx.base.concurrency.container;

import com.csx.base.concurrency.util.TimeUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;

/**
 * <p> what does this class do ? </p>
 *   这个案例是 CopyOnWriteArrayList 的使用案例
 *   描述:
 *     内部包含一个 EventListener 接口,用于定义 事件监听器；EventListenerManager 类用于管理所有
 *     的 EventListener.其内部使用 CopyOnWriteArrayList 来完成 EventListener 的增删改操作
 *   CopyOnWriteArrayList的使用场景:
 *     1. 适用于 读多写少 的场景; 不适用于 写多 的场景，否则大量使用 synchronized锁 造成存储效率不高，而且涉及大量数据复制
 *     2. 适用于 较少数据的存储。 因为每次写入数据时都会复制一份原先的数据，如果存储的数据量很大，这个开销无疑是巨大的
 *     3. 适用于 时效性不敏感的场景。 由于读取时读的是旧的集合，写入未彻底完成前无法读取到最新的数据，不适合实时性要求比较高的场景
 * <p> How does it work ?</p>
 * <p> Why does it do this ?</p>
 *
 * @author cuisongxu
 * @date 2024/12/6 周五 8:46
 */
public class CopyOnWriteArrayListTest {

    public static void main(String[] args) {
        CopyOnWriteArrayListTest copyOnWriteArrayListTest = new CopyOnWriteArrayListTest();
        copyOnWriteArrayListTest.test();
    }

    // 入口方法
    public void test() {

        EventListenerManager instance = EventListenerManager.getInstance();

        // 向事件管理器中添加三个 EventListener 事件监听器
        instance.addListener(new EventListener<String>() {
            @Override
            public void handleEvent(String event) {
                System.out.println("Listener1 处理事件:" + event);
            }

            @Override
            public Class<String> getTargetClass() {
                return String.class;
            }
        });
        instance.addListener(new EventListener<String>() {
            @Override
            public void handleEvent(String event) {
                System.out.println("Listener2 处理事件:" + event);
            }

            @Override
            public Class<String> getTargetClass() {
                return String.class;
            }
        });
        instance.addListener(new EventListener<String>() {
            @Override
            public void handleEvent(String event) {
                System.out.println("Listener3 处理事件:" + event);
            }

            @Override
            public Class<String> getTargetClass() {
                return String.class;
            }
        });

        // 启动两个线程,每个线程都发送10次事件
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                // 模拟发送事件的耗时
                try {
                    TimeUnit.MILLISECONDS.sleep((long) (Math.random() * 100 + 100));
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                String nowTimeStr = TimeUtil.getNowTimeStr();

                instance.notifyListeners(nowTimeStr + " " + Thread.currentThread().getName() + " 发送的事件" + (i+1));
            }
        }, "thread1");
        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                // 模拟发送事件的耗时
                try {
                    TimeUnit.MILLISECONDS.sleep((long) (Math.random() * 100 + 100));
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                String nowTimeStr = TimeUtil.getNowTimeStr();

                instance.notifyListeners(nowTimeStr + " " + Thread.currentThread().getName() + " 发送的事件" + (i+1));
            }
        }, "thread2");

        thread1.start();
        thread2.start();

        try {
            // 等待两个线程执行完毕
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }


    }
    static class EventListenerManager {

        private final CopyOnWriteArrayList<EventListener<?>> listeners = new CopyOnWriteArrayList<>();

        private static volatile EventListenerManager INSTANCE;

        private EventListenerManager() {}

        public void addListener(EventListener<?> listener) {
            listeners.add(listener);
        }

        public void removeListener(EventListener<?> listener) {
            listeners.remove(listener);
        }

        @SuppressWarnings("unchecked")
        public <T> List<EventListener<T>> getListeners(Class<T> eventClass) {

            if(eventClass == null) throw new NullPointerException();
            ArrayList<EventListener<T>> res = new ArrayList<>();
            for (EventListener<?> listener : listeners) {
                
                Class<?> eventType = listener.getTargetClass();
                // eventClass 是 eventType 类型 或者 其子类型时,方法返回true
                if (eventType.isAssignableFrom(eventClass)) {
                    res.add((EventListener<T>) listener);
                }
            }
            return res;
        }

        @SuppressWarnings("unchecked")
        public <T> void notifyListeners(T event) {
            if(event == null) throw new NullPointerException();
            // 获取处理目标 Event 类型的 EventListener 事件监听器
            List<? extends EventListener<?>> targetListeners = getListeners(event.getClass());
            for (EventListener<?> listener : targetListeners) {
                EventListener<T> typedListener = (EventListener<T>) listener;
                // 调用 EventListener.handleEvent(event) 方法处理事件
                typedListener.handleEvent(event);
            }
        }

        public static EventListenerManager getInstance() {
            EventListenerManager temp = INSTANCE;
            if(temp == null) {
                synchronized (EventListenerManager.class) {
                    temp = INSTANCE;
                    if(temp == null) {
                        temp = new EventListenerManager();
                        INSTANCE = temp;
                    }
                }
            }
            return temp;
        }

    }

    interface EventListener<T>  {
        void handleEvent(T event);
        // 处理事件的Class类
        Class<T> getTargetClass();
    }
}
